import React, { Component } from 'react'
import { Modal } from 'antd-mobile'
import AI from './AI'
import config from '../utils/config'

const  { 图片地址 } = config

const 起始布局 = [
    ['C0', 'M0', 'X0', 'S0', 'J0', 'S1', 'X1', 'M1', 'C1'],
    [, , , , , , , ,],
    [, 'P0', , , , , , 'P1',],
    ['Z0', , 'Z1', , 'Z2', , 'Z3', , 'Z4'],
    [, , , , , , , ,],
    [, , , , , , , ,],
    ['z0', , 'z1', , 'z2', , 'z3', , 'z4'],
    [, 'p0', , , , , , 'p1',],
    [, , , , , , , ,],
    ['c0', 'm0', 'x0', 's0', 'j0', 's1', 'x1', 'm1', 'c1']
]

const 二维数组克隆 = (arr) => {
    let newArr = [];
    for (let i = 0; i < arr.length; i++) {
        newArr[i] = arr[i].slice();
    }
    return newArr;
}

let 棋盘宽 = 325
let 棋盘高 = 402
let canvas = {}
let ct = {}
let 格宽 = 35
let 格高 = 36
let 着点X = 5
let 着点Y = 19
let 棋子映射 = {}
let 棋子坐标 = 二维数组克隆(起始布局)
let 图片 = {
    背景图片: new Image(),
    提示点: new Image(),
    外框: new Image()
}
let 棋子图片 = {}
let 当前棋子 = undefined
let 可着点 = []
let 走棋记录 = []
let 最近走棋 = {}
let 正在下棋 = true
let 搜索深度 = 4
let 棋盘

const 棋子能走的着点 = {}

//车
棋子能走的着点.c = (x, y, id, 棋子坐标) => {
    var d = [];
    //左侧检索
    for (var i = x - 1; i >= 0; i--) {
        if (棋子坐标[y][i]) {
            if (棋子映射[棋子坐标[y][i]].id != id) d.push([i, y]);
            break
        } else {
            d.push([i, y])
        }
    }
    //右侧检索
    for (var i = x + 1; i <= 8; i++) {
        if (棋子坐标[y][i]) {
            if (棋子映射[棋子坐标[y][i]].id != id) d.push([i, y]);
            break
        } else {
            d.push([i, y])
        }
    }
    //上检索
    for (var i = y - 1; i >= 0; i--) {
        if (棋子坐标[i][x]) {
            if (棋子映射[棋子坐标[i][x]].id != id) d.push([x, i]);
            break
        } else {
            d.push([x, i])
        }
    }
    //下检索
    for (var i = y + 1; i <= 9; i++) {
        if (棋子坐标[i][x]) {
            if (棋子映射[棋子坐标[i][x]].id != id) d.push([x, i]);
            break
        } else {
            d.push([x, i])
        }
    }
    return d;
}

//马
棋子能走的着点.m = (x, y, id, 棋子坐标) => {
    var d = [];
    //1点
    if (y - 2 >= 0 && x + 1 <= 8 && !棋子坐标[y - 1][x] && (!棋子映射[棋子坐标[y - 2][x + 1]] || 棋子映射[棋子坐标[y - 2][x + 1]].id != id)) d.push([x + 1, y - 2]);
    //2点
    if (y - 1 >= 0 && x + 2 <= 8 && !棋子坐标[y][x + 1] && (!棋子映射[棋子坐标[y - 1][x + 2]] || 棋子映射[棋子坐标[y - 1][x + 2]].id != id)) d.push([x + 2, y - 1]);
    //4点
    if (y + 1 <= 9 && x + 2 <= 8 && !棋子坐标[y][x + 1] && (!棋子映射[棋子坐标[y + 1][x + 2]] || 棋子映射[棋子坐标[y + 1][x + 2]].id != id)) d.push([x + 2, y + 1]);
    //5点
    if (y + 2 <= 9 && x + 1 <= 8 && !棋子坐标[y + 1][x] && (!棋子映射[棋子坐标[y + 2][x + 1]] || 棋子映射[棋子坐标[y + 2][x + 1]].id != id)) d.push([x + 1, y + 2]);
    //7点
    if (y + 2 <= 9 && x - 1 >= 0 && !棋子坐标[y + 1][x] && (!棋子映射[棋子坐标[y + 2][x - 1]] || 棋子映射[棋子坐标[y + 2][x - 1]].id != id)) d.push([x - 1, y + 2]);
    //8点
    if (y + 1 <= 9 && x - 2 >= 0 && !棋子坐标[y][x - 1] && (!棋子映射[棋子坐标[y + 1][x - 2]] || 棋子映射[棋子坐标[y + 1][x - 2]].id != id)) d.push([x - 2, y + 1]);
    //10点
    if (y - 1 >= 0 && x - 2 >= 0 && !棋子坐标[y][x - 1] && (!棋子映射[棋子坐标[y - 1][x - 2]] || 棋子映射[棋子坐标[y - 1][x - 2]].id != id)) d.push([x - 2, y - 1]);
    //11点
    if (y - 2 >= 0 && x - 1 >= 0 && !棋子坐标[y - 1][x] && (!棋子映射[棋子坐标[y - 2][x - 1]] || 棋子映射[棋子坐标[y - 2][x - 1]].id != id)) d.push([x - 1, y - 2]);

    return d;
}

//相
棋子能走的着点.x = (x, y, id, 棋子坐标) => {
    var d = [];
    if (id === 1) { //红方
        //4点半
        if (y + 2 <= 9 && x + 2 <= 8 && !棋子坐标[y + 1][x + 1] && (!棋子映射[棋子坐标[y + 2][x + 2]] || 棋子映射[棋子坐标[y + 2][x + 2]].id != id)) d.push([x + 2, y + 2]);
        //7点半
        if (y + 2 <= 9 && x - 2 >= 0 && !棋子坐标[y + 1][x - 1] && (!棋子映射[棋子坐标[y + 2][x - 2]] || 棋子映射[棋子坐标[y + 2][x - 2]].id != id)) d.push([x - 2, y + 2]);
        //1点半
        if (y - 2 >= 5 && x + 2 <= 8 && !棋子坐标[y - 1][x + 1] && (!棋子映射[棋子坐标[y - 2][x + 2]] || 棋子映射[棋子坐标[y - 2][x + 2]].id != id)) d.push([x + 2, y - 2]);
        //10点半
        if (y - 2 >= 5 && x - 2 >= 0 && !棋子坐标[y - 1][x - 1] && (!棋子映射[棋子坐标[y - 2][x - 2]] || 棋子映射[棋子坐标[y - 2][x - 2]].id != id)) d.push([x - 2, y - 2]);
    } else {
        //4点半
        if (y + 2 <= 4 && x + 2 <= 8 && !棋子坐标[y + 1][x + 1] && (!棋子映射[棋子坐标[y + 2][x + 2]] || 棋子映射[棋子坐标[y + 2][x + 2]].id != id)) d.push([x + 2, y + 2]);
        //7点半
        if (y + 2 <= 4 && x - 2 >= 0 && !棋子坐标[y + 1][x - 1] && (!棋子映射[棋子坐标[y + 2][x - 2]] || 棋子映射[棋子坐标[y + 2][x - 2]].id != id)) d.push([x - 2, y + 2]);
        //1点半
        if (y - 2 >= 0 && x + 2 <= 8 && !棋子坐标[y - 1][x + 1] && (!棋子映射[棋子坐标[y - 2][x + 2]] || 棋子映射[棋子坐标[y - 2][x + 2]].id != id)) d.push([x + 2, y - 2]);
        //10点半
        if (y - 2 >= 0 && x - 2 >= 0 && !棋子坐标[y - 1][x - 1] && (!棋子映射[棋子坐标[y - 2][x - 2]] || 棋子映射[棋子坐标[y - 2][x - 2]].id != id)) d.push([x - 2, y - 2]);
    }
    return d;
}

//士
棋子能走的着点.s = (x, y, id, 棋子坐标) => {
    var d = [];
    if (id === 1) { //红方
        //4点半
        if (y + 1 <= 9 && x + 1 <= 5 && (!棋子映射[棋子坐标[y + 1][x + 1]] || 棋子映射[棋子坐标[y + 1][x + 1]].id != id)) d.push([x + 1, y + 1]);
        //7点半
        if (y + 1 <= 9 && x - 1 >= 3 && (!棋子映射[棋子坐标[y + 1][x - 1]] || 棋子映射[棋子坐标[y + 1][x - 1]].id != id)) d.push([x - 1, y + 1]);
        //1点半
        if (y - 1 >= 7 && x + 1 <= 5 && (!棋子映射[棋子坐标[y - 1][x + 1]] || 棋子映射[棋子坐标[y - 1][x + 1]].id != id)) d.push([x + 1, y - 1]);
        //10点半
        if (y - 1 >= 7 && x - 1 >= 3 && (!棋子映射[棋子坐标[y - 1][x - 1]] || 棋子映射[棋子坐标[y - 1][x - 1]].id != id)) d.push([x - 1, y - 1]);
    } else {
        //4点半
        if (y + 1 <= 2 && x + 1 <= 5 && (!棋子映射[棋子坐标[y + 1][x + 1]] || 棋子映射[棋子坐标[y + 1][x + 1]].id != id)) d.push([x + 1, y + 1]);
        //7点半
        if (y + 1 <= 2 && x - 1 >= 3 && (!棋子映射[棋子坐标[y + 1][x - 1]] || 棋子映射[棋子坐标[y + 1][x - 1]].id != id)) d.push([x - 1, y + 1]);
        //1点半
        if (y - 1 >= 0 && x + 1 <= 5 && (!棋子映射[棋子坐标[y - 1][x + 1]] || 棋子映射[棋子坐标[y - 1][x + 1]].id != id)) d.push([x + 1, y - 1]);
        //10点半
        if (y - 1 >= 0 && x - 1 >= 3 && (!棋子映射[棋子坐标[y - 1][x - 1]] || 棋子映射[棋子坐标[y - 1][x - 1]].id != id)) d.push([x - 1, y - 1]);
    }
    return d;

}

//将
棋子能走的着点.j = (x, y, id, 棋子坐标) => {
    var d = [];
    var isNull = (function () {
        var y1 = 棋子映射["j0"].y;
        var x1 = 棋子映射["J0"].x;
        var y2 = 棋子映射["J0"].y;
        for (var i = y1 - 1; i > y2; i--) {
            if (棋子坐标[i][x1]) return false;
        }
        return true;
    })();

    if (id === 1) { //红方
        //下
        if (y + 1 <= 9 && (!棋子映射[棋子坐标[y + 1][x]] || 棋子映射[棋子坐标[y + 1][x]].id != id)) d.push([x, y + 1]);
        //上
        if (y - 1 >= 7 && (!棋子映射[棋子坐标[y - 1][x]] || 棋子映射[棋子坐标[y - 1][x]].id != id)) d.push([x, y - 1]);
        //老将对老将的情况
        if (棋子映射["j0"].x == 棋子映射["J0"].x && isNull) d.push([棋子映射["J0"].x, 棋子映射["J0"].y]);

    } else {
        //下
        if (y + 1 <= 2 && (!棋子映射[棋子坐标[y + 1][x]] || 棋子映射[棋子坐标[y + 1][x]].id != id)) d.push([x, y + 1]);
        //上
        if (y - 1 >= 0 && (!棋子映射[棋子坐标[y - 1][x]] || 棋子映射[棋子坐标[y - 1][x]].id != id)) d.push([x, y - 1]);
        //老将对老将的情况
        if (棋子映射["j0"].x == 棋子映射["J0"].x && isNull) d.push([棋子映射["j0"].x, 棋子映射["j0"].y]);
    }
    //右
    if (x + 1 <= 5 && (!棋子映射[棋子坐标[y][x + 1]] || 棋子映射[棋子坐标[y][x + 1]].id != id)) d.push([x + 1, y]);
    //左
    if (x - 1 >= 3 && (!棋子映射[棋子坐标[y][x - 1]] || 棋子映射[棋子坐标[y][x - 1]].id != id)) d.push([x - 1, y]);
    return d;
}

//炮
棋子能走的着点.p = (x, y, id, 棋子坐标) => {
    var d = [];
    //左侧检索
    var n = 0;
    for (var i = x - 1; i >= 0; i--) {
        if (棋子坐标[y][i]) {
            if (n == 0) {
                n++;
                continue;
            } else {
                if (棋子映射[棋子坐标[y][i]].id != id) d.push([i, y]);
                break
            }
        } else {
            if (n == 0) d.push([i, y])
        }
    }
    //右侧检索
    var n = 0;
    for (var i = x + 1; i <= 8; i++) {
        if (棋子坐标[y][i]) {
            if (n == 0) {
                n++;
                continue;
            } else {
                if (棋子映射[棋子坐标[y][i]].id != id) d.push([i, y]);
                break
            }
        } else {
            if (n == 0) d.push([i, y])
        }
    }
    //上检索
    var n = 0;
    for (var i = y - 1; i >= 0; i--) {
        if (棋子坐标[i][x]) {
            if (n == 0) {
                n++;
                continue;
            } else {
                if (棋子映射[棋子坐标[i][x]].id != id) d.push([x, i]);
                break
            }
        } else {
            if (n == 0) d.push([x, i])
        }
    }
    //下检索
    var n = 0;
    for (var i = y + 1; i <= 9; i++) {
        if (棋子坐标[i][x]) {
            if (n == 0) {
                n++;
                continue;
            } else {
                if (棋子映射[棋子坐标[i][x]].id != id) d.push([x, i]);
                break
            }
        } else {
            if (n == 0) d.push([x, i])
        }
    }
    return d;
}

//卒
棋子能走的着点.z = (x, y, id, 棋子坐标) => {
    var d = [];
    if (id === 1) { //红方
        //上
        if (y - 1 >= 0 && (!棋子映射[棋子坐标[y - 1][x]] || 棋子映射[棋子坐标[y - 1][x]].id != id)) d.push([x, y - 1]);
        //右
        if (x + 1 <= 8 && y <= 4 && (!棋子映射[棋子坐标[y][x + 1]] || 棋子映射[棋子坐标[y][x + 1]].id != id)) d.push([x + 1, y]);
        //左
        if (x - 1 >= 0 && y <= 4 && (!棋子映射[棋子坐标[y][x - 1]] || 棋子映射[棋子坐标[y][x - 1]].id != id)) d.push([x - 1, y]);
    } else {
        //下
        if (y + 1 <= 9 && (!棋子映射[棋子坐标[y + 1][x]] || 棋子映射[棋子坐标[y + 1][x]].id != id)) d.push([x, y + 1]);
        //右
        if (x + 1 <= 8 && y >= 6 && (!棋子映射[棋子坐标[y][x + 1]] || 棋子映射[棋子坐标[y][x + 1]].id != id)) d.push([x + 1, y]);
        //左
        if (x - 1 >= 0 && y >= 6 && (!棋子映射[棋子坐标[y][x - 1]] || 棋子映射[棋子坐标[y][x - 1]].id != id)) d.push([x - 1, y]);
    }

    return d;
}

const 棋子价值 = {
    //车价值
    c: [
        [206, 208, 207, 213, 214, 213, 207, 208, 206],
        [206, 212, 209, 216, 233, 216, 209, 212, 206],
        [206, 208, 207, 214, 216, 214, 207, 208, 206],
        [206, 213, 213, 216, 216, 216, 213, 213, 206],
        [208, 211, 211, 214, 215, 214, 211, 211, 208],

        [208, 212, 212, 214, 215, 214, 212, 212, 208],
        [204, 209, 204, 212, 214, 212, 204, 209, 204],
        [198, 208, 204, 212, 212, 212, 204, 208, 198],
        [200, 208, 206, 212, 200, 212, 206, 208, 200],
        [194, 206, 204, 212, 200, 212, 204, 206, 194]
    ],

    //马价值
    m: [
        [90, 90, 90, 96, 90, 96, 90, 90, 90],
        [90, 96, 103, 97, 94, 97, 103, 96, 90],
        [92, 98, 99, 103, 99, 103, 99, 98, 92],
        [93, 108, 100, 107, 100, 107, 100, 108, 93],
        [90, 100, 99, 103, 104, 103, 99, 100, 90],

        [90, 98, 101, 102, 103, 102, 101, 98, 90],
        [92, 94, 98, 95, 98, 95, 98, 94, 92],
        [93, 92, 94, 95, 92, 95, 94, 92, 93],
        [85, 90, 92, 93, 78, 93, 92, 90, 85],
        [88, 85, 90, 88, 90, 88, 90, 85, 88]
    ],

    //相价值
    x: [
        [0, 0, 20, 0, 0, 0, 20, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 23, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 20, 0, 0, 0, 20, 0, 0],

        [0, 0, 20, 0, 0, 0, 20, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0],
        [18, 0, 0, 0, 23, 0, 0, 0, 18],
        [0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 20, 0, 0, 0, 20, 0, 0]
    ],

    //士价值
    s: [
        [0, 0, 0, 20, 0, 20, 0, 0, 0],
        [0, 0, 0, 0, 23, 0, 0, 0, 0],
        [0, 0, 0, 20, 0, 20, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0],

        [0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 20, 0, 20, 0, 0, 0],
        [0, 0, 0, 0, 23, 0, 0, 0, 0],
        [0, 0, 0, 20, 0, 20, 0, 0, 0]
    ],

    //奖价值
    j: [
        [0, 0, 0, 8888, 8888, 8888, 0, 0, 0],
        [0, 0, 0, 8888, 8888, 8888, 0, 0, 0],
        [0, 0, 0, 8888, 8888, 8888, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0],

        [0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 8888, 8888, 8888, 0, 0, 0],
        [0, 0, 0, 8888, 8888, 8888, 0, 0, 0],
        [0, 0, 0, 8888, 8888, 8888, 0, 0, 0]
    ],

    //炮价值
    p: [

        [100, 100, 96, 91, 90, 91, 96, 100, 100],
        [98, 98, 96, 92, 89, 92, 96, 98, 98],
        [97, 97, 96, 91, 92, 91, 96, 97, 97],
        [96, 99, 99, 98, 100, 98, 99, 99, 96],
        [96, 96, 96, 96, 100, 96, 96, 96, 96],

        [95, 96, 99, 96, 100, 96, 99, 96, 95],
        [96, 96, 96, 96, 96, 96, 96, 96, 96],
        [97, 96, 100, 99, 101, 99, 100, 96, 97],
        [96, 97, 98, 98, 98, 98, 98, 97, 96],
        [96, 96, 97, 99, 99, 99, 97, 96, 96]
    ],

    //卒价值
    z: [
        [9, 9, 9, 11, 13, 11, 9, 9, 9],
        [19, 24, 34, 42, 44, 42, 34, 24, 19],
        [19, 24, 32, 37, 37, 37, 32, 24, 19],
        [19, 23, 27, 29, 30, 29, 27, 23, 19],
        [14, 18, 20, 27, 29, 27, 20, 18, 14],

        [7, 0, 13, 0, 16, 0, 13, 0, 7],
        [7, 0, 7, 0, 15, 0, 7, 0, 7],
        [0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0]
    ]
}

//黑子为红字价值位置的倒置
棋子价值.C = 二维数组克隆(棋子价值.c).reverse();
棋子价值.M = 二维数组克隆(棋子价值.m).reverse();
棋子价值.X = 棋子价值.x;
棋子价值.S = 棋子价值.s;
棋子价值.J = 棋子价值.j;
棋子价值.P = 二维数组克隆(棋子价值.p).reverse();
棋子价值.Z = 二维数组克隆(棋子价值.z).reverse();

const 棋子配置 = {
    //红子 中文/图片地址/阵营/权重
    'c': { text: "车", img: 'r_c', id: 1, 种类: "c", value: 棋子价值.c },
    'm': { text: "马", img: 'r_m', id: 1, 种类: "m", value: 棋子价值.m },
    'x': { text: "相", img: 'r_x', id: 1, 种类: "x", value: 棋子价值.x },
    's': { text: "仕", img: 'r_s', id: 1, 种类: "s", value: 棋子价值.s },
    'j': { text: "将", img: 'r_j', id: 1, 种类: "j", value: 棋子价值.j },
    'p': { text: "炮", img: 'r_p', id: 1, 种类: "p", value: 棋子价值.p },
    'z': { text: "兵", img: 'r_z', id: 1, 种类: "z", value: 棋子价值.z },

    //蓝子
    'C': { text: "車", img: 'b_c', id: -1, 种类: "c", value: 棋子价值.C },
    'M': { text: "馬", img: 'b_m', id: -1, 种类: "m", value: 棋子价值.M },
    'X': { text: "象", img: 'b_x', id: -1, 种类: "x", value: 棋子价值.X },
    'S': { text: "士", img: 'b_s', id: -1, 种类: "s", value: 棋子价值.S },
    'J': { text: "帅", img: 'b_j', id: -1, 种类: "j", value: 棋子价值.J },
    'P': { text: "炮", img: 'b_p', id: -1, 种类: "p", value: 棋子价值.P },
    'Z': { text: "卒", img: 'b_z', id: -1, 种类: "z", value: 棋子价值.Z }
}

class 棋子 {
    constructor(key, x, y) {
        this.key = key
        this.x = x
        this.y = y
        this.alpha = 1

        let 棋名 = key.slice(0, 1)
        this.id = 棋子配置[棋名].id
        this.value = 棋子配置[棋名].value
    }

    显示 = () => {
        ct.save()
        ct.globalAlpha = this.alpha
        ct.drawImage(棋子图片[this.key.slice(0, 1)], this.x * 格宽 + 着点X, this.y * 格高 + 着点Y)
        ct.restore()
    }

    可着点 = (棋子坐标) => {
        return 棋子能走的着点[棋子配置[this.key.slice(0, 1)].种类](this.x, this.y, this.id, 棋子坐标)
    }
}

const 点击棋盘 = (e) => {
    if (!正在下棋) {
        return
    }
    let { x, y } = 获取点击点(e);
    let key = 获取点击棋子(x, y);

    if (key) {
        点击棋子(key, x, y);
    } else if (当前棋子) {
        走棋(x, y);
    }
}

const 获取点击棋子 = (x, y) => {
    if (x < 0 || x > 8 || y < 0 || y > 9) {
        return false;
    }
    return (棋子坐标[y][x] && 棋子坐标[y][x] != "0") ? 棋子坐标[y][x] : false;
}

const 获取点击点 = (e) => {
    let { x, y } = 获取画布位置();
    x = Math.round((e.pageX - x - 着点X - 20) / 格宽)
    y = Math.round((e.pageY - y - 着点Y - 20) / 格高)
    return { "x": x, "y": y }
}

const 获取画布位置 = () => {
    let left = canvas.offsetLeft
    let top = canvas.offsetTop
    let current = canvas.offsetParent
    while (current !== null) {
        left += current.offsetLeft
        top += current.offsetTop
        current = current.offsetParent
    }
    return { x: left, y: top }
}

const 点击棋子 = (key, x, y) => {
    let 棋子 = 棋子映射[key]
    //吃子
    if (当前棋子 && 当前棋子.key != key && 棋子.id != 棋子映射[当前棋子.key].id && 检测是否可着点(x, y)) {
        delete 棋子映射[key]
        棋子映射[当前棋子.key].alpha = 1
        棋子映射[当前棋子.key].x = x
        棋子映射[当前棋子.key].y = y
        delete 棋子坐标[当前棋子.y][当前棋子.x]
        棋子坐标[y][x] = 当前棋子.key
        最近走棋 = {
            oldX: 当前棋子.x,
            oldY: 当前棋子.y,
            newX: x,
            newY: y
        }
        当前棋子 = undefined
        可着点 = []
        走棋记录.push(二维数组克隆(棋子坐标))
        显示()
        if (key == "j0") {
            棋盘.红方获胜()
            正在下棋 = false
            return
        }
        if (key == "J0") {
            棋盘.蓝方获胜()
            正在下棋 = false
            return
        }
        AI走棋()
    } else if (棋子.id == 1) { // 选中棋子
        棋子.alpha = 0.6
        if (当前棋子) {
            棋子映射[当前棋子.key].alpha = 1
        }
        当前棋子 = { ...棋子 }
        可着点 = 棋子.可着点(棋子坐标)
        显示()
    }
}

const 走棋 = (x, y) => {
    var key = 当前棋子.key;
    if (key && 检测是否可着点(x, y)) {
        delete 棋子坐标[当前棋子.y][当前棋子.x];
        棋子坐标[y][x] = key;
        可着点 = []
        棋子映射[key].x = x
        棋子映射[key].y = y
        棋子映射[key].alpha = 1
        最近走棋 = {
            oldX: 当前棋子.x,
            oldY: 当前棋子.y,
            newX: x,
            newY: y
        }
        当前棋子 = undefined
        可着点 = []
        走棋记录.push(二维数组克隆(棋子坐标))
        显示()
        AI走棋()
    }
}

const AI走棋 = () => {
    setTimeout(_ => {
        const ai走棋 = AI.走棋(棋子坐标, 棋子映射, 搜索深度)
        if (!ai走棋) { // 输了
            棋盘.红方获胜()
            正在下棋 = false
            return
        }

        const { oldX, oldY, newX, newY } = ai走棋
        let oldKey = 棋子坐标[oldY][oldX]
        let newKey = 棋子坐标[newY][newX]
        棋子坐标[newY][newX] = 棋子坐标[oldY][oldX]
        delete 棋子坐标[oldY][oldX]
        if (newKey) {
            delete 棋子映射[newKey]
        }
        棋子映射[oldKey].x = newX
        棋子映射[oldKey].y = newY
        最近走棋 = {
            oldX,
            oldY,
            newX,
            newY
        }
        当前棋子 = undefined
        可着点 = []
        走棋记录.push(二维数组克隆(棋子坐标))
        显示()
        if (newKey == "j0") {
            棋盘.蓝方获胜()
            正在下棋 = false
            return
        }
        if (newKey == "J0") {
            棋盘.红方获胜()
            正在下棋 = false
            return
        }
        if (AI.是否获胜(棋子坐标, 棋子映射, 搜索深度)) {
            棋盘.蓝方获胜()
            正在下棋 = false
        }
    }, 500)
}

const 检测是否可着点 = (x, y) => {
    for (let i = 0; i < 可着点.length; i++) {
        if (可着点[i][0] == x && 可着点[i][1] == y) {
            return true
        }
    }
    return false
}

const 显示 = () => {
    ct.clearRect(0, 0, 棋盘宽, 棋盘高)

    // 绘制背景
    ct.drawImage(图片.背景图片, 0, 0)

    // 绘制棋子
    for (let key in 棋子映射) {
        棋子映射[key].显示()
    }

    // 绘制可着点
    for (let i = 0; i < 可着点.length; i++) {
        ct.save()
        ct.drawImage(图片.提示点, 可着点[i][0] * 格宽 + 着点X + 10, 可着点[i][1] * 格高 + 着点Y + 10)
        ct.restore()
    }

    // 绘制最近走棋
    const { oldX, oldY, newX, newY } = 最近走棋
    if (oldX || oldY || newX || newY) {
        ct.drawImage(图片.外框, oldX * 格宽 + 着点X, oldY * 格高 + 着点Y)
        ct.drawImage(图片.外框, newX * 格宽 + 着点X, newY * 格高 + 着点Y)
    }
}

class App extends Component {
    constructor(props) {
        super(props)
    }
    componentDidMount = () => {
        棋盘 = this
        canvas = document.getElementById("画布")
        ct = canvas.getContext("2d")

        图片.背景图片.src = 图片地址 + "img/stype_1/bg.png"
        图片.提示点.src = 图片地址 + "img/stype_1/dot.png"
        图片.外框.src = 图片地址 + "img/stype_1/r_box.png"

        for (let key in 棋子配置) {
            const img = new Image()
            img.src = 图片地址 + "img/stype_1/" + 棋子配置[key].img + ".png"
            棋子图片[key] = img
        }

        setTimeout(() => {
            棋盘.开始()
        }, 400)
    }
    初始化 = (AI搜索深度) => {
        搜索深度 = AI搜索深度
    }
    开始 = (布局) => {
        if (!布局) {
            布局 = 起始布局
            走棋记录 = []
            走棋记录.push(二维数组克隆(棋子坐标))
        }

        最近走棋 = {}
        当前棋子 = undefined
        正在下棋 = true
        棋子坐标 = 二维数组克隆(布局)
        棋子映射 = {}
        for (let i = 0; i < 布局.length; i++) {
            for (let j = 0; j < 布局[i].length; j++) {
                let key = 布局[i][j]
                if (key) {
                    棋子映射[key] = new 棋子(key, j, i)
                }
            }
        }
        显示()
    }
    悔棋 = () => {
        if (走棋记录.length >= 2) {
            走棋记录.pop()
            走棋记录.pop()
            this.开始(走棋记录[走棋记录.length - 1])
        }
    }
    蓝方获胜 = () => {
        Modal.alert("AI获胜", "是否再来一局?", [{
            text: "是",
            onPress: _ => {
                this.开始()
            }
        }, {
            text: "悔棋",
            onPress: _ => {
                this.悔棋()
            }
        }])
    }

    红方获胜 = () => {
        Modal.alert("您获胜了", "是否再来一局?", [{
            text: "是",
            onPress: _ => {
                this.开始()
            }
        }, {
            text: "悔棋",
            onPress: _ => {
                this.悔棋()
            }
        }])
    }
    render() {
        return (
            <div style={{ width: 棋盘宽, height: 棋盘高 }}>
                <canvas id="画布" width={棋盘宽} height={棋盘高} onClick={点击棋盘}>
                    对不起，您的浏览器不支持HTML5，请升级浏览器至IE9、firefox或者谷歌浏览器！
                </canvas>
            </div>
        )
    }
}

export default App